// module ysyx_050369_DIV  ( 
//     input              clk,
//     input              rst,
//     input  [63:0]      dividend,
//     input  [63:0]      divisor,
//     input              div_valid,
//     input              divw,
//     input              div_signed,
//     input              flush,
//     output reg         div_ready,
//     output reg         out_valid,
//     output reg [63:0]  quotient,//商
//     output reg [63:0]  remainder//  余数
// );
//     parameter IDLE=0,READY=1,RUN=2,RES=3,OUT=4,HIT_RES=5;
//     reg  [3: 0]   state,next_state;
//     reg  [127:0]  dividend_temp;
//     reg  [64:0]   divisor_temp;
//     reg  [2 :0]   sign;
//     reg  [63:0]   res;
//     reg  [6 :0]   cycle;
//     reg  [6 :0]   cnt;
//     wire [62:0]   dividend_64,divisor_64;
//     wire [63:0]   dividend_temp_64,res_64;
//     wire [30:0]   dividend_32,divisor_32;
//     wire [64:0]   sub_res;
//     reg [129:0] input_buffer ;
//     reg [127:0] out_buffer   ;
//     wire        hit;
//     // wire        hit_num;
//     assign dividend_64 = (div_signed && dividend[63])?~dividend[62:0]+1:dividend[62:0];
//     assign divisor_64  = (div_signed && divisor[63] )? ~divisor [62:0]+1:divisor[62:0];
//     assign dividend_32 = (div_signed && dividend[31])?~dividend[30:0]+1:dividend[30:0];
//     assign divisor_32  = (div_signed && divisor[31] )? ~divisor [30:0]+1:divisor[30:0];
//     assign sub_res = dividend_temp[127:63]-divisor_temp;
//     assign dividend_temp_64 = ~dividend_temp[127:64]+1;
//     assign res_64 = ~res+1;

//     assign hit = ({divw,div_signed,divisor,dividend} == input_buffer) ? 1'b1 :1'b0;

//     always @(posedge clk ) begin
//         if (rst||flush) state <= IDLE;
//         else state <= next_state;
//     end
//     always @(*) begin
//         case (state)
//             IDLE: next_state = div_valid? (|hit)? HIT_RES:READY:IDLE;
//             READY:next_state = RUN;
//             RUN:  next_state = (cnt == cycle)?RES:RUN;
//             RES:  next_state = OUT;
//             OUT:  next_state = IDLE;
//             HIT_RES:next_state = IDLE;
//             default: begin end
//         endcase
//     end
//     always @(posedge clk ) begin
//         if (rst)begin
//             cnt           <= 'b0;
//             cycle         <= 'b0;
//             dividend_temp <= 'b0;
//             divisor_temp  <= 'b0;
//             out_valid     <= 'b0; 
//             div_ready     <= 'b1;
//             quotient      <= 'b0;
//             remainder     <= 'b0;
//             sign          <= 'b0;
//             input_buffer  <= 130'b0;
//             out_buffer    <= 128'b0;
//         end
//         else begin
            
//             case (next_state)
//                 IDLE:begin
//                     cnt           <= 'b0;
//                     cycle         <= 'b0;
//                     dividend_temp <= 'b0;
//                     divisor_temp  <= 'b0;
//                     out_valid     <= 'b0; 
//                     div_ready     <= 'b1;
//                     sign          <= 'b0;
//                 end 
//                 READY:begin
//                     div_ready <= 1'b0;
//                     sign[2]   <= divw;
//                     sign[1]   <=dividend[63]&div_signed;
//                     sign[0]   <=divisor[63]&div_signed;
//                     // sign[0]   <=(divisor[63]^dividend[63])&div_signed;
//                     cycle     <= divw?7'd32:7'd64;
//                     dividend_temp <= divw?  {64'b0,~div_signed&&dividend[31],dividend_32,32'b0}:
//                                             {64'b0,~div_signed&&dividend[63],dividend_64};
//                     divisor_temp  <= divw?  {33'b0,~div_signed&&divisor[31],divisor_32}:
//                                             {1'b0,~div_signed&&divisor[63],divisor_64};
//                 end
//                 RUN:begin
//                     if (dividend_temp[127:63]>=divisor_temp) begin
//                         dividend_temp[127:63] <= {sub_res[63:0],dividend_temp[62]};
//                         res                <= {res[62:0],1'b1};
//                     end
//                     else begin
//                         dividend_temp[127:63] <= dividend_temp[126:62];
//                         res                <= {res[62:0],1'b0};
//                     end
//                     dividend_temp [62:0] <= {dividend_temp [61:0],1'b0};
//                     cnt <= cnt +1 ;
//                 end
//                 RES:begin
//                     case (sign)
//                         3'b000:begin
//                             quotient   <= res;
//                             remainder  <= dividend_temp[127:64];
//                         end
//                         3'b010:begin
//                             quotient   <= res_64;
//                             remainder  <= dividend_temp_64;
//                         end
//                         3'b001:begin
//                             quotient   <= res_64;
//                             remainder  <= dividend_temp[127:64];
//                         end
//                         3'b011:begin
//                             quotient   <= res;
//                             remainder  <= dividend_temp_64;
//                         end 
//                         3'b100:begin
//                             quotient   <= {32'b0,res[31:0]};
//                             remainder  <= {32'b0,dividend_temp[95:64]};
//                         end
//                         3'b110:begin
//                             quotient   <= {{32{res_64[31]}},res_64[31:0]};
//                             remainder  <= {{32{dividend_temp_64[31]}},dividend_temp_64[31:0]};
//                         end
//                         3'b101:begin
//                             quotient   <= {{32{res_64[31]}},res_64[31:0]};
//                             remainder  <= {{32{dividend_temp[95]}},dividend_temp[95:64]};
//                         end
//                         3'b111:begin
//                             quotient   <= {{32{res[31]}},res[31:0]};
//                             remainder  <=  {{32{dividend_temp_64[31]}},dividend_temp_64[31:0]};
//                         end 
//                         default: begin end 
//                     endcase
//                 end
//                 OUT:begin
//                     out_valid  <= 1'b1;
//                     input_buffer   <= {divw,div_signed,divisor,dividend};
//                     out_buffer     <= {quotient,remainder};
//                     // end
//                 end
//                 HIT_RES:begin
//                     out_valid       <= 1'b1;
//                     remainder       <= out_buffer[63:0];
//                     quotient        <= out_buffer[127:64];
//                 end
//                 default: begin end
//             endcase
//         end
//     end
// endmodule

module ysyx_050369_DIV  ( 
    input              clk,
    input              rst,
    input  [63:0]      dividend,
    input  [63:0]      divisor,
    input              div_valid,
    input              divw,
    input              div_signed,
    input              flush,
    output reg         div_ready,
    output reg         out_valid,
    output reg [63:0]  quotient,//商
    output reg [63:0]  remainder//  余数
);
    parameter IDLE=0,READY=1,RUN=2,RES=3,OUT=4,HIT_RES=5;
    reg  [3: 0]   state,next_state;
    reg  [127:0]  dividend_temp;
    reg  [64:0]   divisor_temp;
    wire  [1 :0]   sign;
    reg  [63:0]   res;
    reg  [6 :0]   cycle;
    reg  [6 :0]   cnt;
    wire [63:0]   dividend_abs,divisor_abs;
    wire [63:0]   res_w;
    wire [127:0]  dividend_w;
    wire [64:0]   sub_res;
    reg [129:0] input_buffer ;
    reg [127:0] out_buffer   ;
    wire        hit;
    // wire        hit_num;
    assign sign[1]      = (divw?dividend[31]:dividend[63])&div_signed;
    assign sign[0]      = (divw?divisor[31]:divisor[63])&div_signed;
    assign dividend_abs = (sign[1])?~dividend+1:dividend;
    assign divisor_abs  = (sign[0] )?~divisor +1:divisor;
    assign sub_res = dividend_temp[127:63]-divisor_temp;
    assign dividend_w = {{sign[1]?~dividend_temp[127:64]+1:dividend_temp[127:64]},dividend_temp[63:0]};
    assign res_w = (sign[1]^sign[0])?~res+1 : res;

    assign hit = ({divw,div_signed,divisor,dividend} == input_buffer) ? 1'b1 :1'b0;

    always @(posedge clk ) begin
        if (rst||flush) state <= IDLE;
        else state <= next_state;
    end
    always @(*) begin
        case (state)
            IDLE: next_state = div_valid? (|hit)? HIT_RES:READY:IDLE;
            READY:next_state = RUN;
            RUN:  next_state = (cnt == cycle)?RES:RUN;
            RES:  next_state = OUT;
            OUT:  next_state = IDLE;
            HIT_RES:next_state = IDLE;
            default: begin end
        endcase
    end
    always @(posedge clk ) begin
        if (rst)begin
            cnt           <= 'b0;
            cycle         <= 'b0;
            dividend_temp <= 'b0;
            divisor_temp  <= 'b0;
            out_valid     <= 'b0; 
            div_ready     <= 'b1;
            quotient      <= 'b0;
            remainder     <= 'b0;
            input_buffer  <= 130'b0;
            out_buffer    <= 128'b0;
        end
        else begin
            
            case (next_state)
                IDLE:begin
                    cnt           <= 'b0;
                    cycle         <= 'b0;
                    dividend_temp <= 'b0;
                    divisor_temp  <= 'b0;
                    out_valid     <= 'b0; 
                    div_ready     <= 'b1;
                end 
                READY:begin
                    div_ready <= 1'b0;
                    
                    cycle     <= divw?7'd32:7'd64;
                    dividend_temp <= divw?  {64'b0,dividend_abs[31:0],32'b0}:
                                            {64'b0,dividend_abs};
                    divisor_temp  <= divw?  {33'b0,divisor_abs[31:0]}:
                                            {1'b0,divisor_abs};
                end
                RUN:begin
                    if (dividend_temp[127:63]>=divisor_temp) begin
                        dividend_temp[127:64] <= sub_res[63:0];
                        res                <= {res[62:0],1'b1};
                    end
                    else begin
                        dividend_temp[127:63] <= dividend_temp[126:62];
                        res                <= {res[62:0],1'b0};
                    end
                    dividend_temp [63:0] <= {dividend_temp [62:0],1'b0};
                    cnt <= cnt +1 ;
                end
                RES:begin
                    quotient <= divw ?   {{32{res_w[31]}}, res_w[31:0]}:
                                            res_w;
                    remainder<= divw ?   {{32{dividend_w[95]}},dividend_w[95:64]}:
                                            dividend_w[127:64];
                end
                OUT:begin
                    out_valid  <= 1'b1;
                    input_buffer   <= {divw,div_signed,divisor,dividend};
                    out_buffer     <= {quotient,remainder};
                    // end
                end
                HIT_RES:begin
                    out_valid       <= 1'b1;
                    remainder       <= out_buffer[63:0];
                    quotient        <= out_buffer[127:64];
                end
                default: begin end
            endcase
        end
    end
endmodule